from typing import List, Dict, Set
from .player import Player
from .hand_evaluator import PokerHand
from collections import defaultdict

class Pot:
    """底池类"""
    def __init__(self):
        self.amount = 0
        self.max_bet = 0
        self.eligible_players = set()
        
    def add_bet(self, amount: int):
        self.amount += amount

class PotManager:
    """边池管理器"""
    def __init__(self):
        self.pots = [Pot()]  # 主池和边池列表
        self.player_bets = defaultdict(int)  # 记录每个玩家的总下注额
        self._total_pot = 0  # 总底池
        
    def add_bet(self, player: Player, amount: int):
        """处理玩家的下注"""
        self.player_bets[player] += amount
        self._total_pot += amount
        
        # 更新所有池
        self._update_pots()
    
    def _update_pots(self):
        """更新所有池"""
        # 重置所有池
        self.pots = []
        remaining_bets = self.player_bets.copy()
        
        # 使用堆来优化最小值查找
        while remaining_bets:
            pot = Pot()
            # 找出当前最小的下注额
            min_bet = min(bet for bet in remaining_bets.values() if bet > 0)
            
            # 使用列表推导式优化循环
            contributions = [
                (player, min(bet, min_bet))
                for player, bet in remaining_bets.items()
                if bet > 0
            ]
            
            # 批量更新底池
            pot.amount = sum(contribution for _, contribution in contributions)
            pot.eligible_players.update(
                player for player, _ in contributions
            )
            
            # 批量更新剩余下注
            remaining_bets = {
                player: bet - contribution
                for (player, contribution), (_, bet) 
                in zip(contributions, remaining_bets.items())
                if bet - contribution > 0
            }
            
            pot.max_bet = min_bet
            self.pots.append(pot)
    
    def get_pot_size(self) -> int:
        """获取总底池大小"""
        return self._total_pot
    
    def get_player_investment(self, player: Player) -> int:
        """获取玩家的总投资"""
        return self.player_bets.get(player, 0)
    
    def get_eligible_pots(self, player: Player) -> List[Pot]:
        """获取玩家有资格赢取的底池"""
        return [pot for pot in self.pots if player in pot.eligible_players]
    
    def get_pot_odds(self, player: Player, call_amount: int) -> float:
        """计算底池赔率"""
        if call_amount == 0:
            return float('inf')
        return self._total_pot / call_amount
    
    def clear(self):
        """清空底池"""
        self.pots = [Pot()]
        self.player_bets.clear()
        self._total_pot = 0
    
    def distribute_pot(self, player_hands: Dict[Player, PokerHand]) -> Dict[Player, int]:
        """分配奖池给获胜者
        
        Args:
            player_hands: 玩家和他们的手牌字典
            
        Returns:
            每个玩家赢得的筹码数（正数表示赢，负数表示输）
        """
        # 初始化所有参与下注玩家的输赢记录（初始为负的下注额）
        winnings = {player: -bet for player, bet in self.player_bets.items()}
        
        # 对每个池进行分配
        for pot in self.pots:
            # 找出有资格赢得该池的玩家中牌最大的
            eligible_hands = {p: h for p, h in player_hands.items() 
                            if p in pot.eligible_players and not p.is_folded}
            if not eligible_hands:
                continue
                
            # 找出最大的手牌
            best_hand = max(eligible_hands.values())
            
            # 找出所有持有最大手牌的玩家
            winners = [p for p, h in eligible_hands.items() if h == best_hand]
            
            # 平均分配该池
            share = pot.amount // len(winners)
            remainder = pot.amount % len(winners)
            
            # 分配奖池给获胜者
            for i, winner in enumerate(winners):
                # 如果是最后一个赢家且有余数，加上余数
                extra = remainder if i == len(winners) - 1 else 0
                win_amount = share + extra
                
                # 更新赢家的输赢记录（加上赢得的金额）
                winnings[winner] += win_amount
                
                # 更新赢家的筹码
                winner.win_pot(win_amount)
                
                # 确保赢家的总收益不为负
                if winnings[winner] <= 0 and len(winners) == 1:
                    winnings[winner] = win_amount
        
        return winnings
    
    @property
    def total_pot(self) -> int:
        """返回所有池的总金额"""
        return self._total_pot
    
    def get_min_raise(self) -> int:
        """获取当前最小加注额"""
        if not self.player_bets:
            return 0
        return max(self.player_bets.values()) 